home *** CD-ROM | disk | FTP | other *** search
- /*
- * ACKNOWLEDGEMENTS
- *
- * ZMDM was derived from rz/sz for Unix posted by
- * Chuck Forsberg (...!tektronix!reed!omen!caf ). We
- * thank him for his excellent code, and for giving
- * us permission to use and distribute his code and
- * documentation.
- *
- * Atari St version by:
- * Jwahar Bammi
- * bang: uunet!cadence!bammi
- * domain: bammi@cadence.com
- * GEnie: J.Bammi
- * CIS: 71515,155
- */
-
- /*
- * Z M . C
- * ZMODEM protocol primitives
- * 05-24-89 Chuck Forsberg Omen Technology Inc
- *
- * Entry point Functions:
- * zsbhdr(type, hdr) send binary header
- * zshhdr(type, hdr) send hex header
- * zgethdr(hdr, eflag) receive header - binary or hex
- * zsdata(buf, len, frameend) send data
- * zrdata(buf, len) receive data
- * stohdr(pos) store position data in Txhdr
- * long rclhdr(hdr) recover position offset from header
- *
- * This version implements ZMODEM Run Length Encoding, Comparision,
- * and variable length headers. These features were not funded
- * by the original Telenet development contract. This software,
- * including these features, may be freely used for non
- * commercial and educational purposes. This software may also
- * be freely used to support file transfer operations to or from
- * licensed Omen Technology products. Contact Omen Technology
- * for licensing for other uses. Any programs which use part or
- * all of this software must be provided in source form with this
- * notice intact except by written permission from Omen
- * Technology Incorporated.
- *
- * Omen Technology Inc FAX: 503-621-3745
- * Post Office Box 4681
- * Portland OR 97208
- *
- * Previous versions of this program (not containing the extensions
- * listed above) remain in the public domain.
- *
- * This code is made available in the hope it will be useful,
- * BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
- * DAMAGES OF ANY KIND.
- *
- */
- #include "config.h"
- #include "zmdm.h"
- #include "common.h"
-
- #ifndef CANFDX
- #include "zmodem.h"
- #endif
-
- #define xsendline(X) sendline(X)
-
- static char *badcrc = "Bad CRC";
- static lastsent; /* Last char we sent */
- static Not8bit; /* Seven bits seen on header */
- static char *frametypes[] = {
- "No Response to Error Correction Request", /* -4 */
- "Carrier Lost", /* -3 */
- "TIMEOUT", /* -2 */
- "ERROR", /* -1 */
- #define FTOFFSET 3
- "ZRQINIT",
- "ZRINIT",
- "ZSINIT",
- "ZACK",
- "ZFILE",
- "ZSKIP",
- "ZNAK",
- "ZABORT",
- "ZFIN",
- "ZRPOS",
- "ZDATA",
- "ZEOF",
- "ZFERR",
- "ZCRC",
- "ZCHALLENGE",
- "ZCOMPL",
- "ZCAN",
- "ZFREECNT",
- "ZCOMMAND",
- "ZSTDERR",
- "xxxxx"
- #define FRTYPES 22 /* Total number of frame types in this array */
- /* not including psuedo negative entries */
- };
-
- #define flushmo flush_modem
-
- /* Send ZMODEM binary header hdr of type type */
- void zsbhdr(len, type, hdr)
- int len, type;
- register char *hdr;
- {
- register int n;
- register unsigned short crc;
-
- #ifndef DSZ
- vfile2("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
- frametypes[type+FTOFFSET], rclhdr(hdr));
- #endif
- if (type == ZDATA)
- for (n = Znulls; --n >=0; )
- xsendline(0);
-
- xsendline(ZPAD); xsendline(ZDLE);
-
- switch (Crc32t=Txfcs32) {
- case 2:
- zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
- flushmo(); break;
- case 1:
- zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32); break;
- default:
- if (Usevhdrs) {
- xsendline(ZVBIN);
- zsendline(len);
- }
- else
- xsendline(ZBIN);
- zsendline(type);
- crc = updcrc(type, 0);
-
- for (n=len; --n >= 0; ++hdr) {
- zsendline(*hdr);
- crc = updcrc((0377& *hdr), crc);
- }
- crc = updcrc(0,updcrc(0,crc));
- zsendline(crc>>8);
- zsendline(crc);
- }
- if (type != ZDATA)
- flushmo();
- }
-
- /* Send ZMODEM binary header hdr of type type */
- void zsbh32(len, hdr, type, flavour)
- int len, type, flavour;
- register char *hdr;
- {
- register int n;
- register unsigned long crc;
-
- xsendline(flavour);
- if (Usevhdrs)
- zsendline(len);
- zsendline(type);
- crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
-
- for (n=len; --n >= 0; ++hdr) {
- crc = UPDC32((0377 & *hdr), crc);
- zsendline(*hdr);
- }
- crc = ~crc;
- for (n=4; --n >= 0;) {
- zsendline((unsigned int)crc);
- crc >>= 8;
- }
- }
-
- /* Send ZMODEM HEX header hdr of type type */
- void zshhdr(len, type, hdr)
- int len, type;
- register char *hdr;
- {
- register int n;
- register unsigned int crc;
-
- #ifndef DSZ
- vfile2("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
- frametypes[type+FTOFFSET], rclhdr(hdr));
- #endif
- sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
- if (Usevhdrs) {
- sendline(ZVHEX);
- zputhex(len);
- }
- else
- sendline(ZHEX);
- zputhex(type);
- Crc32t = 0;
-
- crc = updcrc(type, 0);
- for (n=len; --n >= 0; ++hdr) {
- zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
- }
- crc = updcrc(0,updcrc(0,crc));
- zputhex(crc>>8); zputhex(crc);
-
- /* Make it printable on remote machine */
- sendline(015); sendline(0212);
- /*
- * Uncork the remote in case a fake XOFF has stopped data flow
- */
- if (type != ZFIN && type != ZACK)
- sendline(021);
- flushmo();
- }
-
- /*
- * Send binary array buf of length length, with ending ZDLE sequence frameend
- */
- static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
-
- void zsdata(buf, length, frameend)
- register char *buf;
- int length, frameend;
- {
- register unsigned short crc;
-
- #ifndef DSZ
- vfile2("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
- #endif
- switch (Crc32t) {
- case 1:
- zsda32(buf, length, frameend); break;
- case 2:
- zsdar32(buf, length, frameend); break;
- default:
- crc = 0;
- for (;--length >= 0; ++buf) {
- zsendline(*buf); crc = updcrc((0377 & *buf), crc);
- }
- xsendline(ZDLE); xsendline(frameend);
- crc = updcrc(frameend, crc);
-
- crc = updcrc(0,updcrc(0,crc));
- zsendline(crc>>8); zsendline(crc);
- }
- if (frameend == ZCRCW) {
- xsendline(XON); flushmo();
- }
- }
-
- void zsda32(buf, length, frameend)
- int length, frameend;
- register char *buf;
- {
- register int c;
- register unsigned long crc;
-
- crc = 0xFFFFFFFFL;
- for (;--length >= 0; ++buf) {
- c = *buf & 0377;
- if (c & 0140)
- xsendline(lastsent = c);
- else
- zsendline(c);
- crc = UPDC32(c, crc);
- }
- xsendline(ZDLE); xsendline(frameend);
- crc = UPDC32(frameend, crc);
-
- crc = ~crc;
- for (c=4; --c >= 0;) {
- zsendline((unsigned int)crc); crc >>= 8;
- }
- }
-
- /*
- * Receive array buf of max length with ending ZDLE sequence
- * and CRC. Returns the ending character or error code.
- * NB: On errors may store length+1 bytes!
- */
- int zrdata(buf, length)
- register char *buf;
- int length;
- {
- register int c;
- register unsigned short crc;
- register char *end;
- register int d;
-
- switch (Crc32r) {
- case 1:
- return zrdat32(buf, length);
- case 2:
- return zrdatr32(buf, length);
- }
-
- crc = Rxcount = 0; end = buf + length;
- while (buf <= end) {
- if ((c = zdlread()) & ~0377) {
- crcfoo:
- switch (c) {
- case GOTCRCE:
- case GOTCRCG:
- case GOTCRCQ:
- case GOTCRCW:
- crc = updcrc((d=c)&0377, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = updcrc(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = updcrc(c, crc);
- if (crc & 0xFFFF) {
- log2(badcrc);
- return ERROR;
- }
- Rxcount = length - (end - buf);
- #ifndef DSZ
- vfile2("zrdata: %d %s", Rxcount,
- Zendnames[d-GOTCRCE&3]);
- #endif
- return d;
- case GOTCAN:
- log2("Sender Canceled");
- return ZCAN;
- case TIMEOUT:
- log2("TIMEOUT");
- return c;
- default:
- garbitch(); return c;
- }
- }
- *buf++ = c;
- crc = updcrc(c, crc);
- }
- #ifdef DSZ
- garbitch();
- #else
- log2("Data subpacket too long");
- #endif
- return ERROR;
- }
-
- int zrdat32(buf, length)
- register char *buf;
- int length;
- {
- register int c;
- register unsigned long crc;
- register char *end;
- register int d;
-
- crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length;
- while (buf <= end) {
- if ((c = zdlread()) & ~0377) {
- crcfoo:
- switch (c) {
- case GOTCRCE:
- case GOTCRCG:
- case GOTCRCQ:
- case GOTCRCW:
- d = c; c &= 0377;
- crc = UPDC32(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = UPDC32(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = UPDC32(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = UPDC32(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = UPDC32(c, crc);
- if (crc != 0xDEBB20E3L) {
- log2(badcrc);
- return ERROR;
- }
- Rxcount = length - (end - buf);
- #ifndef DSZ
- vfile2("zrdat32: %d %s", Rxcount,
- Zendnames[d-GOTCRCE&3]);
- #endif
- return d;
- case GOTCAN:
- log2("Sender Canceled");
- return ZCAN;
- case TIMEOUT:
- log2("TIMEOUT");
- return c;
- default:
- garbitch(); return c;
- }
- }
- *buf++ = c;
- crc = UPDC32(c, crc);
- }
- log2("Data subpacket too long");
- return ERROR;
- }
-
- void garbitch()
- {
- log2("Garbled data subpacket");
- }
-
- /*
- * Read a ZMODEM header to hdr, either binary or hex.
- * eflag controls local display of non zmodem characters:
- * 0: no display
- * 1: display printing characters only
- * 2: display all non ZMODEM characters
- *
- * Set Rxhlen to size of header (default 4) (valid iff good hdr)
- * On success, set Zmodem to 1, set Rxpos and return type of header.
- * Otherwise return negative on error.
- * Return ERROR instantly if ZCRCW sequence, for fast error recovery.
- */
- int zgethdr(hdr, eflag)
- char *hdr;
- int eflag;
- {
- register int c, n, cancount;
-
- n = Zrwindow + Baudrate; /* Max bytes before start of frame */
- Rxframeind = Rxtype = 0;
-
- startover:
- cancount = 5;
- again:
- /* Return immediate ERROR if ZCRCW sequence seen */
- switch (c = readline(Rxtimeout)) {
- case RCDO:
- case TIMEOUT:
- goto fifi;
- case CAN:
- gotcan:
- if (--cancount <= 0) {
- c = ZCAN; goto fifi;
- }
- switch (c = readline(1)) {
- case TIMEOUT:
- goto again;
- case ZCRCW:
- switch (readline(1)) {
- case TIMEOUT:
- c = ERROR; goto fifi;
- case RCDO:
- goto fifi;
- default:
- goto agn2;
- }
- case RCDO:
- goto fifi;
- default:
- break;
- case CAN:
- if (--cancount <= 0) {
- c = ZCAN; goto fifi;
- }
- goto again;
- }
- /* **** FALL THRU TO **** */
- default:
- agn2:
- if ( --n == 0) {
- c = GCOUNT; goto fifi;
- }
- if (eflag && ((c &= 0177) & 0140))
- bttyout(c);
- else if (eflag > 1)
- bttyout(c);
- #ifdef UNIX
- fflush(stderr);
- #endif
- goto startover;
- case ZPAD|0200: /* This is what we want. */
- Not8bit = c;
- case ZPAD: /* This is what we want. */
- break;
- }
- cancount = 5;
- splat:
- switch (c = noxrd7()) {
- case ZPAD:
- goto splat;
- case RCDO:
- case TIMEOUT:
- goto fifi;
- default:
- goto agn2;
- case ZDLE: /* This is what we want. */
- break;
- }
-
-
- Rxhlen = 4; /* Set default length */
- Rxframeind = c = noxrd7();
- switch (c) {
- case ZVBIN32:
- if ((Rxhlen = c = zdlread()) < 0)
- goto fifi;
- if (c > ZMAXHLEN)
- goto agn2;
- Crc32r = 1; c = zrbhd32(hdr); break;
- case ZBIN32:
- if (Usevhdrs)
- goto agn2;
- Crc32r = 1; c = zrbhd32(hdr); break;
- case ZVBINR32:
- if ((Rxhlen = c = zdlread()) < 0)
- goto fifi;
- if (c > ZMAXHLEN)
- goto agn2;
- Crc32r = 2; c = zrbhd32(hdr); break;
- case ZBINR32:
- if (Usevhdrs)
- goto agn2;
- Crc32r = 2; c = zrbhd32(hdr); break;
- case RCDO:
- case TIMEOUT:
- goto fifi;
- case ZVBIN:
- if ((Rxhlen = c = zdlread()) < 0)
- goto fifi;
- if (c > ZMAXHLEN)
- goto agn2;
- Crc32r = 0; c = zrbhdr(hdr); break;
- case ZBIN:
- if (Usevhdrs)
- goto agn2;
- Crc32r = 0; c = zrbhdr(hdr); break;
- case ZVHEX:
- if ((Rxhlen = c = zgethex()) < 0)
- goto fifi;
- if (c > ZMAXHLEN)
- goto agn2;
- Crc32r = 0; c = zrhhdr(hdr); break;
- case ZHEX:
- if (Usevhdrs)
- goto agn2;
- Crc32r = 0; c = zrhhdr(hdr); break;
- case CAN:
- goto gotcan;
- default:
- goto agn2;
- }
- Rxpos = hdr[ZP3] & 0377;
- Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
- Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
- Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
- fifi:
- switch (c) {
- case GOTCAN:
- c = ZCAN;
- /* **** FALL THRU TO **** */
- case ZNAK:
- case ZCAN:
- case ERROR:
- case TIMEOUT:
- case RCDO:
- case GCOUNT:
- log2("Got %s", frametypes[c+FTOFFSET]);
- /* **** FALL THRU TO **** */
- #ifndef DSZ
- default:
- if (c >= -4 && c <= FRTYPES)
- vfile2("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
- frametypes[c+FTOFFSET], Rxpos);
- else
- vfile2("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
- #endif
- }
- /* Use variable length headers if we got one */
- if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
- Usevhdrs = 1;
- return c;
- }
-
- /* Receive a binary style header (type and position) */
- int zrbhdr(hdr)
- register char *hdr;
- {
- register int c, n;
- register unsigned short crc;
-
- if ((c = zdlread()) & ~0377)
- return c;
- Rxtype = c;
- crc = updcrc(c, 0);
-
- for (n=Rxhlen; --n >= 0; ++hdr) {
- if ((c = zdlread()) & ~0377)
- return c;
- crc = updcrc(c, crc);
- *hdr = c;
- }
- if ((c = zdlread()) & ~0377)
- return c;
- crc = updcrc(c, crc);
- if ((c = zdlread()) & ~0377)
- return c;
- crc = updcrc(c, crc);
- if (crc & 0xFFFF) {
- log2(badcrc);
- return ERROR;
- }
- #ifdef ZMODEM
- Protocol = ZMODEM;
- #endif
- Zmodem = 1;
- return Rxtype;
- }
-
- /* Receive a binary style header (type and position) with 32 bit FCS */
- int zrbhd32(hdr)
- register char *hdr;
- {
- register int c, n;
- register unsigned long crc;
-
- if ((c = zdlread()) & ~0377)
- return c;
- Rxtype = c;
- crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
- #ifdef DEBUGZ
- vfile2("zrbhd32 c=%X crc=%lX", c, crc);
- #endif
-
- for (n=Rxhlen; --n >= 0; ++hdr) {
- if ((c = zdlread()) & ~0377)
- return c;
- crc = UPDC32(c, crc);
- *hdr = c;
- #ifdef DEBUGZ
- vfile2("zrbhd32 c=%X crc=%lX", c, crc);
- #endif
- }
- for (n=4; --n >= 0;) {
- if ((c = zdlread()) & ~0377)
- return c;
- crc = UPDC32(c, crc);
- #ifdef DEBUGZ
- vfile2("zrbhd32 c=%X crc=%lX", c, crc);
- #endif
- }
- if (crc != 0xDEBB20E3L) {
- log2(badcrc);
- return ERROR;
- }
- #ifdef ZMODEM
- Protocol = ZMODEM;
- #endif
- Zmodem = 1;
- return Rxtype;
- }
-
-
- /* Receive a hex style header (type and position) */
- int zrhhdr(hdr)
- char *hdr;
- {
- register int c;
- register unsigned short crc;
- register int n;
-
- if ((c = zgethex()) < 0)
- return c;
- Rxtype = c;
- crc = updcrc(c, 0);
-
- for (n=Rxhlen; --n >= 0; ++hdr) {
- if ((c = zgethex()) < 0)
- return c;
- crc = updcrc(c, crc);
- *hdr = c;
- }
- if ((c = zgethex()) < 0)
- return c;
- crc = updcrc(c, crc);
- if ((c = zgethex()) < 0)
- return c;
- crc = updcrc(c, crc);
- if (crc & 0xFFFF) {
- log2(badcrc); return ERROR;
- }
- switch ( c = readline(1)) {
- case 0215:
- Not8bit = c;
- /* **** FALL THRU TO **** */
- case 015:
- /* Throw away possible cr/lf */
- switch (c = readline(1)) {
- case 012:
- Not8bit |= c;
- }
- }
- #ifdef ZMODEM
- Protocol = ZMODEM;
- #endif
- Zmodem = 1; return Rxtype;
- }
-
- /* Send a byte as two hex digits */
- void zputhex(c)
- register int c;
- {
- static char digits[] = "0123456789abcdef";
-
- #ifdef DEBUGZ
- if (Verbose>8)
- vfile2("zputhex: %02X", c);
- #endif
- sendline(digits[(((unsigned int)c&0xF0))>>4]);
- sendline(digits[(c)&0xF]);
- }
-
- /*
- * Send character c with ZMODEM escape sequence encoding.
- * Escape XON, XOFF. Escape CR following @ (Telenet net escape)
- */
- void zsendline(c)
- int c;
- {
-
- /* Quick check for non control characters */
- if (c & 0140)
- xsendline(lastsent = c);
- else {
- switch (c &= 0377) {
- case ZDLE:
- xsendline(ZDLE);
- xsendline (lastsent = (c ^= 0100));
- break;
- case 015:
- case 0215:
- if (!Zctlesc && (lastsent & 0177) != '@')
- goto sendit;
- /* **** FALL THRU TO **** */
- case 020:
- case 021:
- case 023:
- case 0220:
- case 0221:
- case 0223:
- xsendline(ZDLE);
- c ^= 0100;
- sendit:
- xsendline(lastsent = c);
- break;
- default:
- if (Zctlesc && ! (c & 0140)) {
- xsendline(ZDLE);
- c ^= 0100;
- }
- xsendline(lastsent = c);
- }
- }
- }
-
- /* Decode two lower case hex digits into an 8 bit byte value */
- int zgethex()
- {
- register int c;
-
- c = zgeth1();
- #ifdef DEBUGZ
- if (Verbose>8)
- vfile2("zgethex: %02X", c);
- #endif
- return c;
- }
-
- int zgeth1()
- {
- register int c, n;
-
- if ((c = noxrd7()) < 0)
- return c;
- n = c - '0';
- if (n > 9)
- n -= ('a' - ':');
- if (n & ~0xF)
- return ERROR;
- if ((c = noxrd7()) < 0)
- return c;
- c -= '0';
- if (c > 9)
- c -= ('a' - ':');
- if (c & ~0xF)
- return ERROR;
- c += (n<<4);
- return c;
- }
-
- /*
- * Read a byte, checking for ZMODEM escape encoding
- * including CAN*5 which represents a quick abort
- */
- int zdlread()
- {
- register int c;
-
- again:
- /* Quick check for non control characters */
- if ((c = readline(Rxtimeout)) & 0140)
- return c;
- switch (c) {
- case ZDLE:
- break;
- case 023:
- case 0223:
- case 021:
- case 0221:
- goto again;
- default:
- if (Zctlesc && !(c & 0140)) {
- goto again;
- }
- return c;
- }
- again2:
- if ((c = readline(Rxtimeout)) < 0)
- return c;
- if (c == CAN && (c = readline(Rxtimeout)) < 0)
- return c;
- if (c == CAN && (c = readline(Rxtimeout)) < 0)
- return c;
- if (c == CAN && (c = readline(Rxtimeout)) < 0)
- return c;
- switch (c) {
- case CAN:
- return GOTCAN;
- case ZCRCE:
- case ZCRCG:
- case ZCRCQ:
- case ZCRCW:
- return (c | GOTOR);
- case ZRUB0:
- return 0177;
- case ZRUB1:
- return 0377;
- case 023:
- case 0223:
- case 021:
- case 0221:
- goto again2;
- default:
- if (Zctlesc && ! (c & 0140)) {
- goto again2;
- }
- if ((c & 0140) == 0100)
- return (c ^ 0100);
- break;
- }
- if (Verbose>1)
- log2("Bad escape sequence %x", c);
- return ERROR;
- }
-
- /*
- * Read a character from the modem line with timeout.
- * Eat parity, XON and XOFF characters.
- */
- int noxrd7()
- {
- register int c;
-
- for (;;) {
- if ((c = readline(Rxtimeout)) < 0)
- return c;
- switch (c &= 0177) {
- case XON:
- case XOFF:
- continue;
- default:
- if (Zctlesc && !(c & 0140))
- continue;
- case '\r':
- case '\n':
- case ZDLE:
- return c;
- }
- }
- }
-
- /* Store long integer pos in Txhdr */
- void stohdr(p)
- long p;
- {
- unsigned long pos = p;
-
- Txhdr[ZP0] = pos;
- Txhdr[ZP1] = pos>>8;
- Txhdr[ZP2] = pos>>16;
- Txhdr[ZP3] = pos>>24;
- }
-
- /* Recover a long integer from a header */
- long
- rclhdr(hdr)
- register char *hdr;
- {
- register long l;
-
- l = (hdr[ZP3] & 0377);
- l = (l << 8) | (hdr[ZP2] & 0377);
- l = (l << 8) | (hdr[ZP1] & 0377);
- l = (l << 8) | (hdr[ZP0] & 0377);
- return l;
- }
-
- /*
- * File: zmr.c 12-04-1988
- * Copyright 1988 Omen Technology Inc All Rights Reserved
- *
- *
- * This code implements ZMODEM Run Length Encoding, not funded
- * by the original Telenet development contract. This software,
- * including these features, may be freely used for non
- * commercial and educational purposes. This software may also
- * be freely used to support file transfer operations to or from
- * licensed Omen Technology products. Contact Omen Technology
- * for licensing for other uses. Any programs which use part or
- * all of this software must be provided in source form with this
- * notice intact except by written permission from Omen
- * Technology Incorporated.
- *
- * Omen Technology Inc FAX: 503-621-3745
- * Post Office Box 4681
- * Portland OR 97208
- *
- * This code is made available in the hope it will be useful,
- * BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
- * DAMAGES OF ANY KIND.
- * ZMODEM RLE compression and decompression functions
- */
-
- /* Send data subpacket RLE encoded with 32 bit FCS */
- void zsdar32(buf, length, frameend)
- char *buf;
- int length, frameend;
- {
- register int c, l, n;
- register unsigned long crc;
-
- crc = 0xFFFFFFFFL; l = *buf++ & 0377;
- if (length == 1) {
- zsendline(l); crc = UPDC32(l, crc);
- if (l == ZRESC) {
- zsendline(1); crc = UPDC32(1, crc);
- }
- } else {
- for (n = 0; --length >= 0; ++buf) {
- if ((c = *buf & 0377) == l && n < 126 && length>0) {
- ++n; continue;
- }
- switch (n) {
- case 0:
- zsendline(l);
- crc = UPDC32(l, crc);
- if (l == ZRESC) {
- zsendline(0100); crc = UPDC32(0100, crc);
- }
- l = c; break;
- case 1:
- if (l != ZRESC) {
- zsendline(l); zsendline(l);
- crc = UPDC32(l, crc);
- crc = UPDC32(l, crc);
- n = 0; l = c; break;
- }
- /* **** FALL THRU TO **** */
- default:
- zsendline(ZRESC); crc = UPDC32(ZRESC, crc);
- if (l == 040 && n < 34) {
- n += 036;
- zsendline(n); crc = UPDC32(n, crc);
- }
- else {
- n += 0101;
- zsendline(n); crc = UPDC32(n, crc);
- zsendline(l); crc = UPDC32(l, crc);
- }
- n = 0; l = c; break;
- }
- }
- }
- xsendline(ZDLE); xsendline(frameend);
- crc = UPDC32(frameend, crc);
-
- crc = ~crc;
- for (length=4; --length >= 0;) {
- zsendline((unsigned int)crc); crc >>= 8;
- }
- }
-
-
- /* Receive data subpacket RLE encoded with 32 bit FCS */
- int zrdatr32(buf, length)
- register char *buf;
- int length;
- {
- register int c;
- register unsigned long crc;
- register char *end;
- register int d;
-
- crc = 0xFFFFFFFFL; Rxcount = 0; end = buf + length;
- d = 0; /* Use for RLE decoder state */
- while (buf <= end) {
- if ((c = zdlread()) & ~0377) {
- crcfoo:
- switch (c) {
- case GOTCRCE:
- case GOTCRCG:
- case GOTCRCQ:
- case GOTCRCW:
- d = c; c &= 0377;
- crc = UPDC32(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = UPDC32(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = UPDC32(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = UPDC32(c, crc);
- if ((c = zdlread()) & ~0377)
- goto crcfoo;
- crc = UPDC32(c, crc);
- if (crc != 0xDEBB20E3L) {
- log2(badcrc);
- return ERROR;
- }
- Rxcount = length - (end - buf);
- #ifndef DSZ
- vfile2("zrdatr32: %d %s", Rxcount,
- Zendnames[d-GOTCRCE&3]);
- #endif
- return d;
- case GOTCAN:
- log2("Sender Canceled");
- return ZCAN;
- case TIMEOUT:
- log2("TIMEOUT");
- return c;
- default:
- log2("Bad data subpacket");
- return c;
- }
- }
- crc = UPDC32(c, crc);
- switch (d) {
- case 0:
- if (c == ZRESC) {
- d = -1; continue;
- }
- *buf++ = c; continue;
- case -1:
- if (c >= 040 && c < 0100) {
- d = c - 035; c = 040; goto spaces;
- }
- if (c == 0100) {
- d = 0;
- *buf++ = ZRESC; continue;
- }
- d = c; continue;
- default:
- d -= 0100;
- if (d < 1)
- goto badpkt;
- spaces:
- if ((buf + d) > end)
- goto badpkt;
- while ( --d >= 0)
- *buf++ = c;
- d = 0; continue;
- }
- }
- badpkt:
- log2("Data subpacket too long");
- return ERROR;
- }
-
- /* -eof- */
-